<template>
  <v-group class="page-group" ref="pageGroup" :config="pageGroupConfig">
    <!--<v-rect :config="pageGroupBgConfig"/>-->
    <v-path :config="pathConfig" v-if="loading"/>
    <v-text :config="errorConfig"
            @mouseenter="setCurror('pointer')"
            @mouseout="setCurror()"
            @click="handleErrorClick" v-else-if="isError"/>
    <v-group class="image-group" v-else :config="imageGroupConfig">
      <!--绘制图片-->
      <v-image :config="imageConfig"/>
      <!--绘制标记、选区-->
      <v-group :config="getMarkGroupConfig(item)" v-for="(item,index) in markShowList" :key="'mark'+index">
        <v-rect :config="getMarkConfig(item)"
                @mouseenter="handleMarkMouseenter(item.mark,$event)"
                @click="handleMarkClick(item.mark,$event)"
                @mouseout="handleMarkMouseout(item.mark,$event)"
        />
        <v-Line :config="getMarkUnderLineConfig(item)"/>
      </v-group>
      <!--绘制涂鸦-->
      <component :is="'v-'+item.className" :config="getScrawlItemConfig(item.attrs,index)"
                 @mouseenter="handleScrawlItemMouseenter(item)"
                 @mouseout="handleScrawlItemMouseout(item)"
                 @click="handleScrawlItemClick(item)"
                 v-for="(item,index) in scrawlShowList"
                 :key="'scrawl'+index" v-if="scrawlShow||isScrawl"/>
      <!--绘制水印-->
      <v-text :config="item" v-for="(item,index) in watermarkList" :key="'watermark'+index"/>
      <!--搜索结果-->
      <v-rect :config="getSearchResultConfig(item)" v-for="(item,index) in searchShowList" :key="'search'+index"/>
      <!--截图 开始-->
      <!--截图遮罩-->
      <v-rect :config="clipMaskConfig" v-if="(pageIndex===currPageIndex)&&isClip"/>
      <v-image :config="clipImageConfig" v-if="(pageIndex===currPageIndex)&&isClip"/>
      <v-circle :config="getAnchorItemConfig(item)" v-for="(item,index) in anchorList"
                @mouseenter="handleAnchorMouseenter(item,$event)"
                @mouseout="handleAnchorMouseout(item,$event)"
                v-if="(pageIndex===currPageIndex)&&isClip"
                :key="'anchor'+index"/>
      <!--截图 结束-->
    </v-group>
  </v-group>
</template>

<script>
  import mixins from "./mixins";

  import getContentLength from "@/util/getContentLength"
  import VueKonva from "@/components/vue-konva";
  import eventBus from "@/util/eventBus";

  let {vGroup, vPath, vImage, vRect, vCircle, vText, vLine, vEllipse, vArrow} = VueKonva

  export default {
    name: "PageView",
    mixins: [mixins],
    components: {vGroup, vPath, vImage, vRect, vCircle, vText, vLine, vEllipse, vArrow},
    props: {
      // pageIndex: Number,
      data: Object
    },
    data() {
      return {
        isError: false,
        imageGroupConfig: {
          name: ``,
          scale: {x: 1, y: 1}
        },
        // imageConfig: {image: null},
        markShowList: [],
        // scrawlShowList: [],
        img: null,
        taskList: [],
        taskRunning: false,
        loading: false,
        loadingRotation: 0,
        loadingInterval: null,
        watermarkList: [],
        searchShowList: [],
        hoverLineIndex: -1
      }
    },
    computed: {
      imageConfig() {
        if (!this.img) return
        return {
          image: this.img,
          stroke: '#00000000',
          shadowColor: this.shadowConfig.shadowColor,
          shadowBlur: this.shadowConfig.shadowBlur
        }
      },
      clipMaskConfig() {
        return {
          width: this.imageGroupConfig.width,
          height: this.imageGroupConfig.height,
          fill: 'rgba(0,0,0,0.4)'
        }
      },
      clipImageConfig() {
        let x = this.clipData.x
        let y = this.clipData.y
        let width = this.clipData.width || 1
        let height = this.clipData.height || 1
        return {
          x,
          y,
          width,
          height,
          crop: {
            x,
            y,
            width,
            height,
          },
          stroke: 'black',
          id: 'clipImage',
          strokeWidth: 1 / this.imageGroupConfig.scale.x / this.scale,
          image: this.img
        }
      },
      errorConfig() {
        return {
          y: this.imageSize.height / 2,
          x: this.imageSize.width / 2,
          height: 50,
          width: 50,
          offsetX: 25,
          offsetY: 25,
          fill: '#f00',
          scale: {
            x: 1 / this.scale * 2,
            y: 1 / this.scale * 2
          },
          text: '加载失败\n\n点击重试'
        }
      },
      pathConfig() {
        return {
          y: this.imageSize.height / 2,
          x: this.imageSize.width / 2,
          height: 50,
          width: 50,
          offsetX: 25,
          offsetY: 25,
          fill: '#8ac3ff',
          rotation: this.loadingRotation,
          scale: {
            x: 1 / this.scale * 2,
            y: 1 / this.scale * 2
          },
          data: `M43.935,25.145c0-10.318-8.364-18.683-18.683-18.683c-10.318,0-18.683,8.365-18.683,18.683h4.068c0-8.071,6.543-14.615,14.615-14.615c8.072,0,14.615,6.543,14.615,14.615H43.935z`
        }
      },
      layer() {
        return this.$parent.getStage()
      },
      pageIndex() {
        return this.data.pageIndex
      },
      scrawlShowList() {
        let arr = []
        let i = this.scrawlList.find(item => item.pageIndex === this.pageIndex)
        if (i) arr = i.data.map(item => {
          let strokeWidth = item.attrs.strokeWidth
          if (strokeWidth) {
            strokeWidth = strokeWidth / this.imageGroupConfig.scale.x
          }
          return {
            ...item,
            strokeWidth
          }
        })
        return arr
      },
      pageGroupConfig() {
        return {
          x: -this.scrollLeft,
          y: this.imageSize.height * this.pageIndex - this.scrollTop + this.imageSize.height / 2,
          width: this.imageSize.width,
          height: this.imageSize.height,
          offsetX: this.imageSize.width / 2,
          offsetY: this.imageSize.height / 2,
          rotation: this.rotation,
          name: `pageGroup${this.pageIndex}`
        }
      },
      pageGroupBgConfig() {
        return {
          width: this.imageSize.width,
          height: this.imageSize.height,
          fill: 'blue',
          shadowEnabled: true,
          shadowColor: 'red',
          shadowBlur: 10,
          // shadowOffset: {x: 10, y: 10},
          shadowOffsetX: 20,
          shadowOffsetY: 50,
          // shadowOpacity: 1,
        }
      },
      anchorList() {
        let clipData = this.clipData
        let x = clipData.x
        let y = clipData.y
        let w = clipData.width
        let h = clipData.height

        let anchorList = [
          {
            name: 'left-top',
            x: x,
            y: y,
          },
          {
            name: 'left-middle',
            x: x,
            y: y + h / 2
          },
          {
            name: 'left-bottom',
            x: x,
            y: y + h
          },
          {
            name: 'center-top',
            x: x + w / 2,
            y: y
          },
          {
            name: 'center-bottom',
            x: x + w / 2,
            y: y + h
          },
          {
            name: 'right-top',
            x: x + w,
            y: y
          },
          {
            name: 'right-middle',
            x: x + w,
            y: y + h / 2
          },
          {
            name: 'right-bottom',
            x: x + w,
            y: y + h
          }
        ]

        return anchorList.map(item => {
          let nul = w === h && h === 1
          return {
            ...item,
            radius: nul || 5,
            fill: nul || 'white',
            stroke: nul || 'black',
            strokeWidth: nul || 1
          }
        })
      },
    },
    watch: {
      markList() {
        this.addTask(this.loadMarkList)
      },
      markShow() {
        this.addTask(this.loadMarkList)
      },
      loading(val) {
        if (val) {
          this.loadingInterval = setInterval(() => {
            this.loadingRotation += 10
            if (this.loadingRotation >= 360) this.loadingRotation = 0
          }, 17)
        } else {
          clearInterval(this.loadingInterval)
        }
      },
      searchResultList() {
        this.addTask(this.loadSearchResult)
      }
    },
    async mounted() {
      await this.initPage()
      // 缓存
      // this.$refs.pageGroup.getNode().cache();
    },
    methods: {
      async initPage() {
        this.loading = true
        this.logger.info('加载页面', this.pageIndex)
        try {
          this.logger.info('页面', this.pageIndex, '开始加载图片')
          let img = await this.getCurrImage()

          this.loadImage(img)
          this.logger.info('页面', this.pageIndex, '图片加载完成')
        } catch (e) {
          this.logger.error('页面', this.pageIndex, '图片加载失败')
          this.logger.error('页面', this.pageIndex, '加载失败')
          this.isError = true
          return
        }
        try {
          this.logger.info('页面', this.pageIndex, '开始加载文字')
          await this.getCurrText()
          this.logger.info('页面', this.pageIndex, '文字加载完成')
        } catch (e) {
          this.logger.error('页面', this.pageIndex, '文字加载失败')
          this.logger.error('页面', this.pageIndex, '加载失败')
          this.isError = true
          return
        }
        this.loading = false
        this.logger.info('页面', this.pageIndex, '加载完成')

        this.addTask(this.loadMarkList)
        this.addTask(this.loadSearchResult)
        this.getWatermarkData()
        this.sendEvent('page-loaded', this.pageIndex)
        this.$nextTick(() => {
          eventBus.emit(`page-loaded-${this.pageIndex}`)
        })
      },
      handleErrorClick() {
        this.initPage()
      },
      getWatermarkData() {
        let watermark = JSON.parse(JSON.stringify(this.watermark))

        if (!watermark || typeof watermark !== 'object') return

        // if (!watermark.spacing) watermark.spacing = {}

        // if (watermark.spacing.x === undefined) watermark.spacing.x = 20
        //
        // if (watermark.spacing.y === undefined) watermark.spacing.y = 20

        /*if (watermark.rotation === undefined) */
        watermark.rotation = 45

        if (watermark.fontSize === undefined) watermark.fontSize = 16 / this.scale

        if (watermark.color === undefined) watermark.color = 'rgba(0,0,0,0.6)'

        if (watermark.text === undefined) watermark.text = '没有水印文字'

        let textHeight = watermark.fontSize * 1.5
        let textWidth = getContentLength(watermark.text) / 2 * watermark.fontSize

        this.watermarkList.push({
          x: this.imageGroupConfig.width / 2,
          y: this.imageGroupConfig.height / 2,
          offset: {
            x: textWidth / 2,
            y: textHeight / 2
          },
          rotation: -45,
          text: watermark.text,
          fontSize: watermark.fontSize,
          fill: watermark.color,
          name: `watermark`,
          listening: false,
          draggable: false
        })
      },
      loadImage(img) {
        let scale = Math.min(this.imageSize.width / img.width, this.imageSize.height / img.height)

        this.imageGroupConfig.x = this.imageSize.width / 2
        this.imageGroupConfig.y = this.imageSize.height / 2
        this.imageGroupConfig.width = img.width
        this.imageGroupConfig.height = img.height
        this.imageGroupConfig.offsetX = img.width / 2
        this.imageGroupConfig.offsetY = img.height / 2
        this.imageGroupConfig.scale = {x: scale, y: scale}
        this.imageGroupConfig.name = `imageGroup${this.pageIndex}`

        this.img = img
      },
      async getCurrImage() {
        let src = await this.data.img()
        return this.getImageBySrc(src)
      },
      getImageBySrc(src) {
        return new Promise((resolve, reject) => {
          let img = new Image()
          img.src = src
          img.onload = () => resolve(img)
          img.onerror = () => reject()
        })
      },
      getCurrText() {
        return this.data.text()
      },
      getMarkUnderLineConfig(config) {
        let c = JSON.parse(JSON.stringify(config))

        let points = [0, c.height, c.width, c.height]

        // if (item.config.type === 'underline') {
        //   // console.log(_item.height)
        //   _item.y = _item.y + _item.height
        //   _item.height = 0
        // }
        return {
          points,
          strokeWidth: c.strokeWidth,
          stroke: c.stroke,
        }
      },
      getMarkConfig(config) {
        let c = JSON.parse(JSON.stringify(config))
        if (c.strokeWidth) c.strokeWidth = c.strokeWidth / this.imageGroupConfig.scale.x / this.scale
        if (c.type === 'underline') {
          c.stroke = 'transparent'
          c.fill = 'transparent'
        }
        return {
          ...c,
          x: 0,
          y: 0
        }
      },
      getMarkGroupConfig(config) {
        let c = JSON.parse(JSON.stringify(config))
        // if (c.strokeWidth) c.strokeWidth = c.strokeWidth / this.imageGroupConfig.scale.x / this.scale
        return {
          x: c.x,
          y: c.y,
          width: c.width,
          height: c.height,
        }
      },
      async loadMarkList() {
        let arr = []
        for (let i = 0; i < this.markList.length; i++) {
          let item = this.markList[i]
          let pageIndex = Number(item.start)
          if (isNaN(pageIndex)) {
            let startIndex = ''
            let endIndex = ''
            if (/^(\d+)-(\d+)$/.test(item.start)) startIndex = Number(RegExp.$1)
            if (/^(\d+)-(\d+)$/.test(item.end)) endIndex = Number(RegExp.$1)
            if (this.pageIndex >= startIndex && this.pageIndex <= endIndex) {
              pageIndex = this.pageIndex
            }
          }
          if ((typeof pageIndex !== 'number') || (pageIndex !== this.pageIndex)) {
            continue
          }
          let show = this.alwaysShowMarkTypes.indexOf(item.type) > -1
          if (!this.markShow && item.config.name !== 'selection' && !show) continue
          // item.config.name==='selection'
          let A = await this.getWordByIndexPos(item.start)
          let B = await this.getWordByIndexPos(item.end)
          let tRows = await this.getWrodsAToB(A, B)
          if (tRows) {
            let text = ''
            for (let name in tRows) {
              let $item = tRows[name]
              text += `${$item.text}\n`
              if ($item.page === this.pageIndex) {
                let _item = {
                  ...item.config,
                  x: $item.x,
                  y: $item.y,
                  width: $item.width,
                  height: $item.height,
                  mark: item
                }
                if (_item.strokeWidth) {
                  _item.strokeWidth = _item.strokeWidth / this.imageGroupConfig.scale.x / this.scale
                }
                if ($item.height < 0) {
                  _item.y = _item.y + $item.height
                  _item.height = Math.abs(_item.height)
                }
                if (!_item.fill && !_item.stroke) {
                  _item.fill = 'rgba(255,0,0,0.3)'
                }
                // if (item.config.type === 'underline') {
                //   // console.log(_item.height)
                //   _item.y = _item.y + _item.height
                //   _item.height = 0
                // }
                arr.push(_item)
              }
            }
            item.text = text.substr(0, text.length - 1)
          } else {
            // if (Number(item.start) === this.pageIndex) {
            let _item = {
              ...item.config,
              ...JSON.parse(item.end),
              mark: item
            }
            if (!_item.fill && !_item.stroke) {
              _item.stroke = 'rgba(255,0,0,1)'
            }
            arr.push(_item)
            // }
          }
        }
        this.markShowList = arr
      },
      async loadSearchResult() {
        let arr = []
        for (let i = 0; i < this.searchResultList.length; i++) {
          let item = this.searchResultList[i]
          let A = item[0]
          let B = item[item.length - 1]
          if (A.pageIndex === this.pageIndex || B.pageIndex === this.pageIndex) {
            let tRows = await this.getWrodsAToB(A, B)
            // let text = ''
            for (let name in tRows) {
              let $item = tRows[name]
              // text += `${$item.text}`
              if ($item.page === this.pageIndex) {
                let _item = {
                  x: $item.x,
                  y: $item.y,
                  width: $item.width,
                  height: $item.height,
                  index: i
                }
                arr.push(_item)
              }
            }
            // item.text = text.substr(0, text.length - 1)

          }
        }
        this.searchShowList = arr
      },
      getSearchResultConfig(item) {
        let fill = 'rgba(255,255,0,0.5)'
        if (this.seachResultIndex - 1 === item.index) {
          fill = 'rgba(255,150,50,0.5)'
        }
        return {
          x: item.x,
          y: item.y,
          width: item.width,
          height: item.height,
          fill
        }
      },
      getScrawlItemConfig(config, index) {
        let isHover = this.hoverLineIndex === config.id && this.scrawlType === 'Eraser'

        let c = JSON.parse(JSON.stringify(config))
        c.strokeWidth = c.strokeWidth / this.imageGroupConfig.scale.x / this.scale
        if (isHover) {
          c.stroke = 'rgba(216,216,216,0.75)'
          c.strokeWidth += 2 / this.imageGroupConfig.scale.x / this.scale
        }
        c.hitStrokeWidth += 5 / this.imageGroupConfig.scale.x / this.scale
        return c
      },
      handleScrawlItemMouseenter(item) {
        this.hoverLineIndex = item.attrs.id
      },
      handleScrawlItemMouseout() {
        this.hoverLineIndex = -1
      },
      handleScrawlItemClick(item) {
        // console.log(item.attrs.id, this.scrawlList)
        this.removeScrawl(item.attrs.id, this.pageIndex)
      },
      handleMarkClick(mark, {evt}) {
        if (mark.markid === 'selection-mark') return
        this.sendEvent('mark-click', mark, evt)
      },
      handleMarkMouseenter(mark, {evt}) {
        if (mark.markid === 'selection-mark') return
        this.sendEvent('mark-mouseenter', mark, evt)
        this.setCurror('pointer')
      },
      handleMarkMouseout(mark, {evt}) {
        if (mark.markid === 'selection-mark') return
        this.sendEvent('mark-mouseout', mark, evt)
        this.setCurror()
      },
      addTask(task) {
        let index = this.taskList.findIndex(item => item === task)
        if (index > -1) this.taskList.splice(index, 1)
        this.taskList.push(task)
        this.runTask()
      },
      async runTask() {
        if (this.taskRunning) return
        this.taskRunning = true
        let task = this.taskList.shift()
        if (!task) return this.taskRunning = false
        await task()
        this.taskRunning = false
        this.runTask()

      },
      handleAnchorMouseenter(item, ev) {
        this.setCurror(item.name)
      },
      getAnchorItemConfig(item) {
        return {
          ...item,
          radius: item.radius / this.imageGroupConfig.scale.x / this.scale,
          strokeWidth: item.strokeWidth / this.imageGroupConfig.scale.x / this.scale,
        }
      },
      handleAnchorMouseout(item, ev) {
        this.setCurror()
      },
      setCurror(cursor = '') {
        this.cursor = cursor
      }
    },
    beforeDestroy() {
      clearInterval(this.loadingInterval)
      this.sendEvent('page-unload', this.pageIndex)
    },
    destroyed() {
      this.logger.info('页面销毁', this.pageIndex)
    }
  }
</script>

<style scoped>
</style>
